<template>
  <div class="menu-tree">
    <el-tree
      ref="treeRef"
      :data="menuTreeData"
      :props="treeProps"
      :default-expand-all="expandAll"
      :expanded-keys="expandedKeys"
      :show-checkbox="showCheckbox"
      :check-strictly="checkStrictly"
      :default-checked-keys="defaultCheckedKeys"
      :draggable="draggable"
      :allow-drop="allowDrop"
      :allow-drag="allowDrag"
      node-key="id"
      @check="handleCheck"
      @node-click="handleNodeClick"
      @node-drop="handleNodeDrop"
      @node-drag-start="handleDragStart"
      @node-drag-end="handleDragEnd"
      @node-expand="handleNodeExpand"
      @node-collapse="handleNodeCollapse"
    >
      <template #default="{ node, data }">
        <div class="menu-node" :class="[
          `level-${data.level}-menu`,
          { 'is-dragging': draggingNodeId === data.id }
        ]">
          <div class="menu-info">
            <el-icon class="menu-icon">
              <component :is="data.icon || 'Document'" />
            </el-icon>
            <span class="menu-name">{{ data.name }}</span>
          </div>
          <div class="menu-actions" v-if="showActions">
            <el-button
              size="small"
              type="text"
              :disabled="isFirstInGroup(data)"
              @click.stop="moveUp(data)"
              title="向上移动"
            >
              <el-icon><ArrowUp /></el-icon>
            </el-button>
            <el-button
              size="small"
              type="text"
              :disabled="isLastInGroup(data)"
              @click.stop="moveDown(data)"
              title="向下移动"
            >
              <el-icon><ArrowDown /></el-icon>
            </el-button>
            <el-button size="small" type="text" @click.stop="editMenu(data)">
              <el-icon><Edit /></el-icon>
            </el-button>
            <el-button size="small" type="text" @click.stop="deleteMenu(data)">
              <el-icon><Delete /></el-icon>
            </el-button>
          </div>
        </div>
      </template>
    </el-tree>
  </div>
</template>

<script setup>
import { ref, computed, watch, nextTick } from 'vue'
import { Edit, Delete, ArrowUp, ArrowDown } from '@element-plus/icons-vue'

// 拖拽状态管理
const draggingNodeId = ref(null)

const props = defineProps({
  menuData: {
    type: Array,
    default: () => []
  },
  showCheckbox: {
    type: Boolean,
    default: false
  },
  showActions: {
    type: Boolean,
    default: false
  },
  expandAll: {
    type: Boolean,
    default: true
  },
  checkStrictly: {
    type: Boolean,
    default: false
  },
  defaultCheckedKeys: {
    type: Array,
    default: () => []
  },
  draggable: {
    type: Boolean,
    default: false
  },
  expandedKeys: {
    type: Array,
    default: () => []
  }
})

const emit = defineEmits(['check', 'node-click', 'edit', 'delete', 'node-drop', 'move-up', 'move-down', 'node-expand', 'node-collapse'])

const treeRef = ref(null)

const treeProps = {
  children: 'children',
  label: 'name'
}

// 构建菜单树数据
const menuTreeData = computed(() => {
  return buildMenuTree(props.menuData)
})

// 构建树形结构
const buildMenuTree = (menus) => {
  const menuMap = {}
  const rootMenus = []

  // 创建菜单映射
  menus.forEach(menu => {
    menuMap[menu.id] = { ...menu, children: [] }
  })

  // 构建树结构
  menus.forEach(menu => {
    if (menu.parent) {
      if (menuMap[menu.parent]) {
        menuMap[menu.parent].children.push(menuMap[menu.id])
      }
    } else {
      rootMenus.push(menuMap[menu.id])
    }
  })

  // 排序
  const sortMenus = (menus) => {
    menus.sort((a, b) => a.sort_order - b.sort_order)
    menus.forEach(menu => {
      if (menu.children && menu.children.length > 0) {
        sortMenus(menu.children)
      }
    })
  }

  sortMenus(rootMenus)
  return rootMenus
}

// 处理复选框变化
const handleCheck = (data, checked) => {
  emit('check', data, checked)
}

// 处理节点点击
const handleNodeClick = (data) => {
  emit('node-click', data)
}

// 编辑菜单
const editMenu = (menu) => {
  emit('edit', menu)
}

// 删除菜单
const deleteMenu = (menu) => {
  emit('delete', menu)
}

// 向上移动
const moveUp = (menu) => {
  emit('move-up', menu)
}

// 向下移动
const moveDown = (menu) => {
  emit('move-down', menu)
}

// 判断是否是同级第一个
const isFirstInGroup = (menu) => {
  const siblings = getSiblings(menu)
  return siblings.length > 0 && siblings[0].id === menu.id
}

// 判断是否是同级最后一个
const isLastInGroup = (menu) => {
  const siblings = getSiblings(menu)
  return siblings.length > 0 && siblings[siblings.length - 1].id === menu.id
}

// 获取同级菜单
const getSiblings = (menu) => {
  return props.menuData
    .filter(m => m.parent === menu.parent && m.level === menu.level)
    .sort((a, b) => a.sort_order - b.sort_order)
}

// 拖拽相关方法
const allowDrop = (draggingNode, dropNode, type) => {
  // 只允许同级拖拽，不允许跨级拖拽
  if (draggingNode.level !== dropNode.level) {
    return false
  }
  // 只允许在节点前后插入，不允许插入到节点内部
  return type !== 'inner'
}

const allowDrag = (draggingNode) => {
  // 允许所有节点拖拽
  return true
}

const handleNodeDrop = (draggingNode, dropNode, dropType) => {
  draggingNodeId.value = null // 拖拽结束，清除状态

  // 添加拖拽完成动画
  if (dropType !== 'none') {
    setTimeout(() => {
      const treeElement = treeRef.value?.$el
      if (treeElement) {
        const draggedElements = treeElement.querySelectorAll(`[data-key="${draggingNode.data.id}"]`)
        draggedElements.forEach(element => {
          const menuNode = element.querySelector('.menu-node')
          if (menuNode) {
            menuNode.classList.add('drag-complete')
            setTimeout(() => {
              menuNode.classList.remove('drag-complete')
            }, 400)
          }
        })
      }
    }, 100)
  }

  emit('node-drop', draggingNode, dropNode, dropType)
}

const handleDragStart = (node, ev) => {
  draggingNodeId.value = node.data.id
}

const handleDragEnd = (draggingNode, dropNode, dropType, ev) => {
  draggingNodeId.value = null

  // 如果拖拽成功，添加移动动画
  if (dropType !== 'none' && dropNode) {
    setTimeout(() => {
      // 查找被拖拽节点的DOM元素并添加动画
      const treeElement = treeRef.value?.$el
      if (treeElement) {
        const draggedElements = treeElement.querySelectorAll(`[data-key="${draggingNode.data.id}"]`)
        draggedElements.forEach(element => {
          const menuNode = element.querySelector('.menu-node')
          if (menuNode) {
            menuNode.classList.add('drag-moving')
            setTimeout(() => {
              menuNode.classList.remove('drag-moving')
            }, 300)
          }
        })
      }
    }, 50)
  }
}

// 处理节点展开
const handleNodeExpand = (data, node) => {
  emit('node-expand', data, node)
}

// 处理节点折叠
const handleNodeCollapse = (data, node) => {
  emit('node-collapse', data, node)
}

// 获取选中的节点
const getCheckedNodes = () => {
  return treeRef.value?.getCheckedNodes() || []
}

// 获取选中的节点ID
const getCheckedKeys = () => {
  return treeRef.value?.getCheckedKeys() || []
}

// 设置选中的节点
const setCheckedKeys = (keys) => {
  treeRef.value?.setCheckedKeys(keys)
}

// 手动恢复展开状态
const restoreExpandedState = () => {
  if (props.expandedKeys && props.expandedKeys.length > 0 && treeRef.value) {
    nextTick(() => {
      props.expandedKeys.forEach(key => {
        const node = treeRef.value.getNode(key)
        if (node && !node.expanded) {
          node.expand()
        }
      })
    })
  }
}

// 监听数据变化，恢复展开状态
watch(() => props.menuData, () => {
  setTimeout(() => {
    restoreExpandedState()
  }, 100)
}, { deep: true })

// 暴露方法给父组件
defineExpose({
  getCheckedNodes,
  getCheckedKeys,
  setCheckedKeys,
  restoreExpandedState
})
</script>

<style scoped>
.menu-tree {
  width: 100%;
}

.menu-node {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 12px 16px;
  margin: 6px 0;
  border-radius: 12px;
  background: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border-left: 4px solid transparent;
  position: relative;
  overflow: hidden;
  transform: translateZ(0); /* 启用硬件加速 */
  will-change: transform, box-shadow; /* 优化动画性能 */
}

.menu-node::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
  transition: left 0.5s ease;
  z-index: 1;
}

.menu-node:hover::before {
  left: 100%;
}

.menu-node:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

/* 一级菜单样式 */
.level-1-menu {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  font-weight: 600;
  border-left: 4px solid #4f46e5;
}

.level-1-menu .menu-icon {
  color: white;
  font-size: 18px;
}

.level-1-menu .menu-name {
  font-size: 16px;
  font-weight: 600;
}

/* 二级菜单样式 */
.level-2-menu {
  background: #f8fafc;
  border-left: 4px solid #10b981;
  margin-left: 24px;
}

.level-2-menu .menu-icon {
  color: #10b981;
  font-size: 16px;
}

.level-2-menu .menu-name {
  color: #374151;
  font-weight: 500;
}

.menu-info {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  position: relative;
  z-index: 2;
}

.menu-icon {
  transition: all 0.3s ease;
}

.menu-name {
  transition: all 0.3s ease;
}



.menu-actions {
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.3s ease;
  position: relative;
  z-index: 2;
}

.menu-node:hover .menu-actions {
  opacity: 1;
}

.menu-actions .el-button {
  padding: 4px 6px;
  min-height: 24px;
}

.menu-actions .el-button:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.menu-actions .el-button[title="向上移动"]:not(:disabled):hover {
  color: #409eff;
  background-color: rgba(64, 158, 255, 0.1);
}

.menu-actions .el-button[title="向下移动"]:not(:disabled):hover {
  color: #409eff;
  background-color: rgba(64, 158, 255, 0.1);
}

/* 拖拽状态 */
.is-dragging {
  opacity: 0.9;
  transform: translateY(-4px) scale(1.02);
  box-shadow: 0 8px 24px rgba(64, 158, 255, 0.25);
  z-index: 1000;
  background-color: rgba(64, 158, 255, 0.08);
  border: 2px solid rgba(64, 158, 255, 0.3);
  border-radius: 12px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 拖拽移动动画 */
.menu-node.drag-moving {
  animation: dragMove 0.3s ease-out;
}

@keyframes dragMove {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-8px);
  }
  100% {
    transform: translateY(0);
  }
}

/* 拖拽目标区域样式 */
.el-tree-node.is-drop-inner > .el-tree-node__content {
  background-color: rgba(64, 158, 255, 0.1);
  border-radius: 8px;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
}

.el-tree-node.is-drop-before > .el-tree-node__content::before {
  content: '';
  position: absolute;
  top: -3px;
  left: 8px;
  right: 8px;
  height: 3px;
  background: linear-gradient(90deg, #409eff, #67c23a);
  border-radius: 2px;
  animation: dropIndicator 1.2s ease-in-out infinite, dropIndicatorPulse 2s ease-in-out infinite;
}

.el-tree-node.is-drop-after > .el-tree-node__content::after {
  content: '';
  position: absolute;
  bottom: -3px;
  left: 8px;
  right: 8px;
  height: 3px;
  background: linear-gradient(90deg, #409eff, #67c23a);
  border-radius: 2px;
  animation: dropIndicator 1.2s ease-in-out infinite, dropIndicatorPulse 2s ease-in-out infinite;
}

/* 拖拽悬停效果 */
.el-tree-node.is-drop-inner > .el-tree-node__content,
.el-tree-node.is-drop-before > .el-tree-node__content,
.el-tree-node.is-drop-after > .el-tree-node__content {
  position: relative;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 拖拽指示器动画 */
@keyframes dropIndicator {
  0%, 100% {
    opacity: 0.7;
    transform: scaleX(0.9) translateY(0);
  }
  50% {
    opacity: 1;
    transform: scaleX(1) translateY(-1px);
  }
}

/* 拖拽指示器呼吸效果 */
@keyframes dropIndicatorPulse {
  0%, 100% {
    box-shadow: 0 1px 4px rgba(64, 158, 255, 0.3);
  }
  50% {
    box-shadow: 0 2px 8px rgba(64, 158, 255, 0.5);
  }
}

/* 拖拽幽灵元素样式 */
.el-tree__drop-indicator {
  height: 3px !important;
  background: linear-gradient(90deg, #409eff, #67c23a) !important;
  border-radius: 2px !important;
  animation: dropIndicator 1.2s ease-in-out infinite, dropIndicatorPulse 2s ease-in-out infinite !important;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
}

/* 拖拽时的光标样式 */
.el-tree-node__content {
  cursor: grab;
}

.el-tree-node__content:active {
  cursor: grabbing;
}

/* 拖拽时禁用文本选择 */
.el-tree.is-dragging {
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

/* 拖拽时的整体容器样式 */
.el-tree-node.is-dragging .el-tree-node__content {
  cursor: grabbing !important;
  transform: translateY(-2px);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 拖拽悬停时的平滑过渡 */
.el-tree-node__content {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 拖拽完成后的回弹效果 */
.menu-node.drag-complete {
  animation: dragComplete 0.4s ease-out;
}

@keyframes dragComplete {
  0% {
    transform: scale(1.05);
  }
  50% {
    transform: scale(0.98);
  }
  100% {
    transform: scale(1);
  }
}

/* Element Plus 树形组件样式覆盖 */
:deep(.el-tree-node__content) {
  height: auto;
  padding: 4px 0;
  background: transparent !important;
  border-radius: 8px;
}

:deep(.el-tree-node__content:hover) {
  background: transparent !important;
}

:deep(.el-tree-node__expand-icon) {
  color: #6b7280;
  font-size: 14px;
}

:deep(.el-tree-node__expand-icon.expanded) {
  transform: rotate(90deg);
}

:deep(.el-tree-node.is-drop-inner > .el-tree-node__content) {
  background-color: #e6f7ff !important;
  border: 2px dashed #1890ff;
}

:deep(.el-tree-node.is-drop-target > .el-tree-node__content) {
  background-color: #f0f9ff !important;
  border: 2px solid #0ea5e9;
}

/* 复选框样式 */
:deep(.el-checkbox) {
  margin-right: 8px;
}

:deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
  background-color: #10b981;
  border-color: #10b981;
}
</style>
